from __future__ import absolute_import

import traceback
import logging
from datetime import datetime, timedelta

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from ae_trace.middleware import get_template
from ae_trace.apps import TraceConfig
from ae_trace.documents import EventTraceDocument as edoc
from ae_trace.models import EventData
from ae_trace.serializer import EventTraceDataSerializer

from common.ploto_response import PlotoResponse
from common.ploto_enum import CommonStatuEnum

from .utils import (es_search, db_search, get_union_field_values,
                    check_body, set_trace_view, get_page_list,
                    response_total)

logger = logging.getLogger(__name__)


class EventTraceData(APIView):

    def __init__(self):
        self.template = get_template(TraceConfig.template_event)
        set_trace_view(self)
        # 将结果倒序排列
        self.order = {
            "es": {
                "create_time": {"order": "desc"}
            },
            "db": "-create_time"
        }


    def get(self, request):
        response = PlotoResponse()
        if not request.user.has_perm('ae_trace.view_eventdata'):
            response.code = CommonStatuEnum.AUTHORIZATION_EXCEPTION.code
            response.msg = CommonStatuEnum.AUTHORIZATION_EXCEPTION.msg
            return Response(response.dict, status=status.HTTP_403_FORBIDDEN)
        body = request.query_params
        if body.get("search_max"):
            self.search_max = int(body.get("search_max"))
        union_field_values = request.session.get("union_field_values_event")
        if body.get('reset') or not union_field_values:
            union_field_values = self.reset_search()
            request.session["union_field_values_event"] = union_field_values
        page = int(body.get('page', 1))
        page_size = int(body.get('page_size', 10))
        if self.search_engine == "es":
            time_field = {"create_time": ["%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S.%f"]}
            body = check_body(body, time_field=time_field, fields=["username"])
            search_res_list = es_search(doc=edoc, order=self.order["es"],
                search_method=self.es_search_method, search_max=self.search_max,
                time_field=["create_time"], **body)
            if search_res_list.total.value == 0:
                return response_total(response, data_list=[], count=0,
                                    union_field_values=union_field_values)

        elif self.search_engine == "db":
            time_field = {"create_time": ["%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f"]}
            body = check_body(body, time_field=time_field, fields=["username"])
            search_res_list = db_search(db_table=EventData, order=self.order["db"],
                search_method=self.db_search_method, search_max=self.search_max, **body)
            if search_res_list.count() == 0:
                return response_total(response, data_list=[], count=0,
                                    union_field_values=union_field_values)
        page_search_res_list, paginator = get_page_list(search_res_list, page, page_size)
        try:
            search_res = EventTraceDataSerializer(instance=page_search_res_list, many=True)
            return response_total(response, data_list=search_res.data,
                                count=paginator.count,
                                union_field_values=union_field_values)
        except Exception as e:
            logger.error("序列化异常: %s, %s", repr(e), traceback.format_exc())
            response.code = CommonStatuEnum.INTERNAL_ERROR.code
            response.msg = CommonStatuEnum.INTERNAL_ERROR.msg
            return Response(response.dict, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def reset_search(self):
        response = PlotoResponse()
        time_format = "%Y-%m-%dT%H:%M:%S.%f" if self.search_engine == "es" else "%Y-%m-%d %H:%M:%S.%f"
        start_time = datetime.strftime(datetime.today() - timedelta(days=180), time_format)
        end_time = datetime.strftime(datetime.today(), time_format)
        reset_body = {"create_time": [start_time, end_time]}
        try:
            if self.search_engine == "es":
                search_res_list = es_search(doc=edoc, order=self.order["es"], search_method=self.es_search_method,
                    search_max=self.search_max, time_field=["create_time"], **reset_body)
            elif self.search_engine == "db":
                search_res_list = db_search(db_table=EventData, order=self.order["db"],
                    search_method=self.db_search_method,
                    search_max=self.search_max, **reset_body)
            return get_union_field_values(search_res_list, self.search_engine, self.union_fields)

        except Exception as e:
            logger.error("reset search failed: %s, %s", repr(e), traceback.format_exc())
            response.code = CommonStatuEnum.INTERNAL_ERROR.code
            response.msg = CommonStatuEnum.INTERNAL_ERROR.msg
            return Response(response.dict, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            